package com.test34_类加载器;

import org.junit.Test;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.lang.reflect.Method;

/**
 * 自定义文件类加载器
 */
public class Demo02_FileClassLoader {

    @Test
    public void test1() {
        // 运行完后，将Message.class文件，复制到F:\muyan目录下
        Message message = new Message();
        System.out.println(message.echo("Hello World"));
    }

    /**
     * 使用自定义加载器对Message类进行加载
     */
    @Test
    public void test2() throws Exception {
        FileClassLoader fileClassLoader = new FileClassLoader();
        Class<?> clazz = fileClassLoader.loadData("com.test26_类加载器.Message");
        Object messageObject = clazz.getDeclaredConstructor().newInstance();
        Method method = clazz.getMethod("echo", String.class);
        System.out.println(method.invoke(messageObject, "沐言优拓：www.yootk.com"));
    }

    /**
     * 最底层类加载器就为自定义的类加载器
     */
    @Test
    public void test3() throws Exception {
        FileClassLoader fileClassLoader = new FileClassLoader();
        Class<?> clazz = fileClassLoader.loadData("com.test26_类加载器.Message");
        ClassLoader loader = clazz.getClassLoader();
        while (loader != null) {
            System.out.println(loader);
            loader = loader.getParent();
        }
    }
}

/**
 * 专属的文件加载器
 */
class FileClassLoader extends ClassLoader {
    private static final String CLASS_FILE_PATH = "F:" + File.separator + "muyan" + File.separator + "Message.class";

    /** 自定义类加载的方法 */
    public Class<?> loadData(String className) throws Exception {
        byte[] data = this.loadFileClassData();     // 加载要使用的类文件
        if (data != null) {
            return super.defineClass(className, data, 0, data.length);  // 创建Class实例
        }
        return null;
    }

    /** 根据给定的文件路径进行加载 */
    private byte[] loadFileClassData() throws Exception {
        InputStream input = new FileInputStream(new File(CLASS_FILE_PATH));
        ByteArrayOutputStream bos = new ByteArrayOutputStream();    // 内存输出流
        input.transferTo(bos);
//        byte[] temp = new byte[100];
//        int len;
//        while ((len = input.read(temp)) != -1) {
//            bos.write(temp, 0, len);
//        }
        // 获取全部的Class文件数据
        byte[] data = bos.toByteArray();
        input.close();
        bos.close();
        return data;
    }
}
